package com.dw.security;

import com.dw.core.entity.Admin;
import com.dw.core.entity.Role;
import com.dw.core.service.IAdminService;
import com.dw.core.service.IPermissionService;
import com.dw.core.service.IRoleService;
import com.dw.web.utils.RedisUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author zhangjing
 * @date 2020/8/21 16:05
 * @Description
 */
public class TokenRealm extends AuthorizingRealm {

    @Autowired
    IAdminService adminService;

    @Autowired
    IRoleService roleService;

    @Autowired
    IPermissionService permissionService;

    @Autowired
    RedisUtils redisUtils;

    @Override
    public String getName() {
        return "Realm";
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token != null && Token.class.isAssignableFrom(token.getClass());
    }

    /**
     * 认证 Authentication
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("认证 Authentication");
        Token token = (Token) authenticationToken;

        Admin admin = redisUtils.get("admin_login_token:" + token.getToken(), Admin.class);
        if (admin == null) {
            return null;
        }
        return new SimpleAuthenticationInfo(admin, token.getToken(), this.getName());
    }

    /**
     * 授权 Authorization
     * @param principal
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        //获取用户的信息
        Admin admin = (Admin) principal.getPrimaryPrincipal();

        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

        // 查询用户拥有的角色key 和 权限key
        List<Role> roles = roleService.findRolesByAdmin(admin);

        Set<String> roleKeys = roles.stream().map(Role::getRoleKey).collect(Collectors.toSet());
        Set<String> permKeys = permissionService.getPermKeysByRoles(roles);

        authorizationInfo.addRoles(roleKeys);
        authorizationInfo.addStringPermissions(permKeys);
        return authorizationInfo;
    }
}
